#include <ctype.h>

#ifdef TIXML_USE_STL
#include <sstream>
#include <iostream>
#endif

#include "tinyxml.h"

FILE* TiXmlFOpen( const char* filename, const char* mode );

bool TiXmlBase::condenseWhiteSpace = true;

FILE* TiXmlFOpen( const char* filename, const char* mode ) {
  #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
  FILE* fp = 0;
  errno_t err = fopen_s( &fp, filename, mode );
  if( !err && fp ) {
    return fp;
  }
  return 0;
  #else
  return fopen( filename, mode );
  #endif
}

void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString ) {
  int i = 0;
  while( i < ( int )str.length() ) {
    unsigned char c = ( unsigned char ) str[i];
    if( c == '&'
        && i < ( ( int )str.length() - 2 )
        && str[i + 1] == '#'
        && str[i + 2] == 'x' ) {
      while( i < ( int )str.length() - 1 ) {
        outString->append( str.c_str() + i, 1 );
        ++i;
        if( str[i] == ';' ) {
          break;
        }
      }
    } else if( c == '&' ) {
      outString->append( entity[0].str, entity[0].strLength );
      ++i;
    } else if( c == '<' ) {
      outString->append( entity[1].str, entity[1].strLength );
      ++i;
    } else if( c == '>' ) {
      outString->append( entity[2].str, entity[2].strLength );
      ++i;
    } else if( c == '\"' ) {
      outString->append( entity[3].str, entity[3].strLength );
      ++i;
    } else if( c == '\'' ) {
      outString->append( entity[4].str, entity[4].strLength );
      ++i;
    } else if( c < 32 ) {
      char buf[ 32 ];
      #if defined(TIXML_SNPRINTF)
      TIXML_SNPRINTF( buf, sizeof( buf ), "&#x%02X;", ( unsigned )( c & 0xff ) );
      #else
      sprintf( buf, "&#x%02X;", ( unsigned )( c & 0xff ) );
      #endif
      outString->append( buf, ( int )strlen( buf ) );
      ++i;
    } else {
      *outString += ( char ) c;
      ++i;
    }
  }
}

TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() {
  parent = 0;
  type = _type;
  firstChild = 0;
  lastChild = 0;
  prev = 0;
  next = 0;
}


TiXmlNode::~TiXmlNode() {
  TiXmlNode* node = firstChild;
  TiXmlNode* temp = 0;
  while( node ) {
    temp = node;
    node = node->next;
    delete temp;
  }
}


void TiXmlNode::CopyTo( TiXmlNode* target ) const {
  target->SetValue( value.c_str() );
  target->userData = userData;
  target->location = location;
}


void TiXmlNode::Clear() {
  TiXmlNode* node = firstChild;
  TiXmlNode* temp = 0;
  while( node ) {
    temp = node;
    node = node->next;
    delete temp;
  }
  firstChild = 0;
  lastChild = 0;
}


TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) {
  assert( node->parent == 0 || node->parent == this );
  assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() );
  if( node->Type() == TiXmlNode::TINYXML_DOCUMENT ) {
    delete node;
    if( GetDocument() ) {
      GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
    }
    return 0;
  }
  node->parent = this;
  node->prev = lastChild;
  node->next = 0;
  if( lastChild ) {
    lastChild->next = node;
  } else {
    firstChild = node;
  }
  lastChild = node;
  return node;
}


TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) {
  if( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) {
    if( GetDocument() ) {
      GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
    }
    return 0;
  }
  TiXmlNode* node = addThis.Clone();
  if( !node ) {
    return 0;
  }
  return LinkEndChild( node );
}


TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) {
  if( !beforeThis || beforeThis->parent != this ) {
    return 0;
  }
  if( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) {
    if( GetDocument() ) {
      GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
    }
    return 0;
  }
  TiXmlNode* node = addThis.Clone();
  if( !node ) {
    return 0;
  }
  node->parent = this;
  node->next = beforeThis;
  node->prev = beforeThis->prev;
  if( beforeThis->prev ) {
    beforeThis->prev->next = node;
  } else {
    assert( firstChild == beforeThis );
    firstChild = node;
  }
  beforeThis->prev = node;
  return node;
}


TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) {
  if( !afterThis || afterThis->parent != this ) {
    return 0;
  }
  if( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) {
    if( GetDocument() ) {
      GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
    }
    return 0;
  }
  TiXmlNode* node = addThis.Clone();
  if( !node ) {
    return 0;
  }
  node->parent = this;
  node->prev = afterThis;
  node->next = afterThis->next;
  if( afterThis->next ) {
    afterThis->next->prev = node;
  } else {
    assert( lastChild == afterThis );
    lastChild = node;
  }
  afterThis->next = node;
  return node;
}


TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) {
  if( !replaceThis ) {
    return 0;
  }
  if( replaceThis->parent != this ) {
    return 0;
  }
  if( withThis.ToDocument() ) {
    TiXmlDocument* document = GetDocument();
    if( document ) {
      document->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
    }
    return 0;
  }
  TiXmlNode* node = withThis.Clone();
  if( !node ) {
    return 0;
  }
  node->next = replaceThis->next;
  node->prev = replaceThis->prev;
  if( replaceThis->next ) {
    replaceThis->next->prev = node;
  } else {
    lastChild = node;
  }
  if( replaceThis->prev ) {
    replaceThis->prev->next = node;
  } else {
    firstChild = node;
  }
  delete replaceThis;
  node->parent = this;
  return node;
}


bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) {
  if( !removeThis ) {
    return false;
  }
  if( removeThis->parent != this ) {
    assert( 0 );
    return false;
  }
  if( removeThis->next ) {
    removeThis->next->prev = removeThis->prev;
  } else {
    lastChild = removeThis->prev;
  }
  if( removeThis->prev ) {
    removeThis->prev->next = removeThis->next;
  } else {
    firstChild = removeThis->next;
  }
  delete removeThis;
  return true;
}

const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const {
  const TiXmlNode* node;
  for( node = firstChild; node; node = node->next ) {
    if( strcmp( node->Value(), _value ) == 0 ) {
      return node;
    }
  }
  return 0;
}


const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const {
  const TiXmlNode* node;
  for( node = lastChild; node; node = node->prev ) {
    if( strcmp( node->Value(), _value ) == 0 ) {
      return node;
    }
  }
  return 0;
}


const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const {
  if( !previous ) {
    return FirstChild();
  } else {
    assert( previous->parent == this );
    return previous->NextSibling();
  }
}


const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const {
  if( !previous ) {
    return FirstChild( val );
  } else {
    assert( previous->parent == this );
    return previous->NextSibling( val );
  }
}


const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const {
  const TiXmlNode* node;
  for( node = next; node; node = node->next ) {
    if( strcmp( node->Value(), _value ) == 0 ) {
      return node;
    }
  }
  return 0;
}


const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const {
  const TiXmlNode* node;
  for( node = prev; node; node = node->prev ) {
    if( strcmp( node->Value(), _value ) == 0 ) {
      return node;
    }
  }
  return 0;
}


void TiXmlElement::RemoveAttribute( const char * name ) {
  #ifdef TIXML_USE_STL
  TIXML_STRING str( name );
  TiXmlAttribute* node = attributeSet.Find( str );
  #else
  TiXmlAttribute* node = attributeSet.Find( name );
  #endif
  if( node ) {
    attributeSet.Remove( node );
    delete node;
  }
}

const TiXmlElement* TiXmlNode::FirstChildElement() const {
  const TiXmlNode* node;
  for( node = FirstChild();
       node;
       node = node->NextSibling() ) {
    if( node->ToElement() ) {
      return node->ToElement();
    }
  }
  return 0;
}


const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const {
  const TiXmlNode* node;
  for( node = FirstChild( _value );
       node;
       node = node->NextSibling( _value ) ) {
    if( node->ToElement() ) {
      return node->ToElement();
    }
  }
  return 0;
}


const TiXmlElement* TiXmlNode::NextSiblingElement() const {
  const TiXmlNode* node;
  for( node = NextSibling();
       node;
       node = node->NextSibling() ) {
    if( node->ToElement() ) {
      return node->ToElement();
    }
  }
  return 0;
}


const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const {
  const TiXmlNode* node;
  for( node = NextSibling( _value );
       node;
       node = node->NextSibling( _value ) ) {
    if( node->ToElement() ) {
      return node->ToElement();
    }
  }
  return 0;
}


const TiXmlDocument* TiXmlNode::GetDocument() const {
  const TiXmlNode* node;
  for( node = this; node; node = node->parent ) {
    if( node->ToDocument() ) {
      return node->ToDocument();
    }
  }
  return 0;
}


TiXmlElement::TiXmlElement( const char * _value )
  : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) {
  firstChild = lastChild = 0;
  value = _value;
}


#ifdef TIXML_USE_STL
TiXmlElement::TiXmlElement( const std::string& _value )
  : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) {
  firstChild = lastChild = 0;
  value = _value;
}
#endif


TiXmlElement::TiXmlElement( const TiXmlElement& copy )
  : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) {
  firstChild = lastChild = 0;
  copy.CopyTo( this );
}


void TiXmlElement::operator=( const TiXmlElement& base ) {
  ClearThis();
  base.CopyTo( this );
}


TiXmlElement::~TiXmlElement() {
  ClearThis();
}


void TiXmlElement::ClearThis() {
  Clear();
  while( attributeSet.First() ) {
    TiXmlAttribute* node = attributeSet.First();
    attributeSet.Remove( node );
    delete node;
  }
}


const char* TiXmlElement::Attribute( const char* name ) const {
  const TiXmlAttribute* node = attributeSet.Find( name );
  if( node ) {
    return node->Value();
  }
  return 0;
}


#ifdef TIXML_USE_STL
const std::string* TiXmlElement::Attribute( const std::string& name ) const {
  const TiXmlAttribute* attrib = attributeSet.Find( name );
  if( attrib ) {
    return &attrib->ValueStr();
  }
  return 0;
}
#endif


const char* TiXmlElement::Attribute( const char* name, int* i ) const {
  const TiXmlAttribute* attrib = attributeSet.Find( name );
  const char* result = 0;
  if( attrib ) {
    result = attrib->Value();
    if( i ) {
      attrib->QueryIntValue( i );
    }
  }
  return result;
}


#ifdef TIXML_USE_STL
const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const {
  const TiXmlAttribute* attrib = attributeSet.Find( name );
  const std::string* result = 0;
  if( attrib ) {
    result = &attrib->ValueStr();
    if( i ) {
      attrib->QueryIntValue( i );
    }
  }
  return result;
}
#endif


const char* TiXmlElement::Attribute( const char* name, double* d ) const {
  const TiXmlAttribute* attrib = attributeSet.Find( name );
  const char* result = 0;
  if( attrib ) {
    result = attrib->Value();
    if( d ) {
      attrib->QueryDoubleValue( d );
    }
  }
  return result;
}


#ifdef TIXML_USE_STL
const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const {
  const TiXmlAttribute* attrib = attributeSet.Find( name );
  const std::string* result = 0;
  if( attrib ) {
    result = &attrib->ValueStr();
    if( d ) {
      attrib->QueryDoubleValue( d );
    }
  }
  return result;
}
#endif


int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const {
  const TiXmlAttribute* attrib = attributeSet.Find( name );
  if( !attrib ) {
    return TIXML_NO_ATTRIBUTE;
  }
  return attrib->QueryIntValue( ival );
}


#ifdef TIXML_USE_STL
int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const {
  const TiXmlAttribute* attrib = attributeSet.Find( name );
  if( !attrib ) {
    return TIXML_NO_ATTRIBUTE;
  }
  return attrib->QueryIntValue( ival );
}
#endif


int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const {
  const TiXmlAttribute* attrib = attributeSet.Find( name );
  if( !attrib ) {
    return TIXML_NO_ATTRIBUTE;
  }
  return attrib->QueryDoubleValue( dval );
}


#ifdef TIXML_USE_STL
int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const {
  const TiXmlAttribute* attrib = attributeSet.Find( name );
  if( !attrib ) {
    return TIXML_NO_ATTRIBUTE;
  }
  return attrib->QueryDoubleValue( dval );
}
#endif


void TiXmlElement::SetAttribute( const char * name, int val ) {
  TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
  if( attrib ) {
    attrib->SetIntValue( val );
  }
}


#ifdef TIXML_USE_STL
void TiXmlElement::SetAttribute( const std::string& name, int val ) {
  TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
  if( attrib ) {
    attrib->SetIntValue( val );
  }
}
#endif


void TiXmlElement::SetDoubleAttribute( const char * name, double val ) {
  TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
  if( attrib ) {
    attrib->SetDoubleValue( val );
  }
}


#ifdef TIXML_USE_STL
void TiXmlElement::SetDoubleAttribute( const std::string& name, double val ) {
  TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
  if( attrib ) {
    attrib->SetDoubleValue( val );
  }
}
#endif


void TiXmlElement::SetAttribute( const char * cname, const char * cvalue ) {
  TiXmlAttribute* attrib = attributeSet.FindOrCreate( cname );
  if( attrib ) {
    attrib->SetValue( cvalue );
  }
}


#ifdef TIXML_USE_STL
void TiXmlElement::SetAttribute( const std::string& _name, const std::string& _value ) {
  TiXmlAttribute* attrib = attributeSet.FindOrCreate( _name );
  if( attrib ) {
    attrib->SetValue( _value );
  }
}
#endif


void TiXmlElement::Print( FILE* cfile, int depth ) const {
  int i;
  assert( cfile );
  for( i = 0; i < depth; i++ ) {
    fprintf( cfile, "    " );
  }
  fprintf( cfile, "<%s", value.c_str() );
  const TiXmlAttribute* attrib;
  for( attrib = attributeSet.First(); attrib; attrib = attrib->Next() ) {
    fprintf( cfile, " " );
    attrib->Print( cfile, depth );
  }
  TiXmlNode* node;
  if( !firstChild ) {
    fprintf( cfile, " />" );
  } else if( firstChild == lastChild && firstChild->ToText() ) {
    fprintf( cfile, ">" );
    firstChild->Print( cfile, depth + 1 );
    fprintf( cfile, "</%s>", value.c_str() );
  } else {
    fprintf( cfile, ">" );
    for( node = firstChild; node; node = node->NextSibling() ) {
      if( !node->ToText() ) {
        fprintf( cfile, "\n" );
      }
      node->Print( cfile, depth + 1 );
    }
    fprintf( cfile, "\n" );
    for( i = 0; i < depth; ++i ) {
      fprintf( cfile, "    " );
    }
    fprintf( cfile, "</%s>", value.c_str() );
  }
}


void TiXmlElement::CopyTo( TiXmlElement* target ) const {
  TiXmlNode::CopyTo( target );
  const TiXmlAttribute* attribute = 0;
  for( attribute = attributeSet.First();
       attribute;
       attribute = attribute->Next() ) {
    target->SetAttribute( attribute->Name(), attribute->Value() );
  }
  TiXmlNode* node = 0;
  for( node = firstChild; node; node = node->NextSibling() ) {
    target->LinkEndChild( node->Clone() );
  }
}

bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const {
  if( visitor->VisitEnter( *this, attributeSet.First() ) ) {
    for( const TiXmlNode* node = FirstChild(); node; node = node->NextSibling() ) {
      if( !node->Accept( visitor ) ) {
        break;
      }
    }
  }
  return visitor->VisitExit( *this );
}


TiXmlNode* TiXmlElement::Clone() const {
  TiXmlElement* clone = new TiXmlElement( Value() );
  if( !clone ) {
    return 0;
  }
  CopyTo( clone );
  return clone;
}


const char* TiXmlElement::GetText() const {
  const TiXmlNode* child = this->FirstChild();
  if( child ) {
    const TiXmlText* childText = child->ToText();
    if( childText ) {
      return childText->Value();
    }
  }
  return 0;
}


TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) {
  tabsize = 4;
  useMicrosoftBOM = false;
  ClearError();
}

TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) {
  tabsize = 4;
  useMicrosoftBOM = false;
  value = documentName;
  ClearError();
}


#ifdef TIXML_USE_STL
TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) {
  tabsize = 4;
  useMicrosoftBOM = false;
  value = documentName;
  ClearError();
}
#endif


TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) {
  copy.CopyTo( this );
}


void TiXmlDocument::operator=( const TiXmlDocument& copy ) {
  Clear();
  copy.CopyTo( this );
}


bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) {
  return LoadFile( Value(), encoding );
}


bool TiXmlDocument::SaveFile() const {
  return SaveFile( Value() );
}

bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding ) {
  TIXML_STRING filename( _filename );
  value = filename;
  FILE* file = TiXmlFOpen( value.c_str(), "rb" );
  if( file ) {
    bool result = LoadFile( file, encoding );
    fclose( file );
    return result;
  } else {
    SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
    return false;
  }
}

bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) {
  if( !file ) {
    SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
    return false;
  }
  Clear();
  location.Clear();
  long length = 0;
  fseek( file, 0, SEEK_END );
  length = ftell( file );
  fseek( file, 0, SEEK_SET );
  if( length <= 0 ) {
    SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
    return false;
  }
  char* buf = new char[ length + 1 ];
  buf[0] = 0;
  if( fread( buf, length, 1, file ) != 1 ) {
    delete [] buf;
    SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
    return false;
  }
  const char* p = buf;
  char* q = buf;
  const char CR = 0x0d;
  const char LF = 0x0a;
  buf[length] = 0;
  while( *p ) {
    assert( p < ( buf + length ) );
    assert( q <= ( buf + length ) );
    assert( q <= p );
    if( *p == CR ) {
      *q++ = LF;
      p++;
      if( *p == LF ) {
        p++;
      }
    } else
    { *q++ = *p++; }
  }
  assert( q <= ( buf + length ) );
  *q = 0;
  Parse( buf, 0, encoding );
  delete [] buf;
  return !Error();
}


bool TiXmlDocument::SaveFile( const char * filename ) const {
  FILE* fp = TiXmlFOpen( filename, "w" );
  if( fp ) {
    bool result = SaveFile( fp );
    fclose( fp );
    return result;
  }
  return false;
}


bool TiXmlDocument::SaveFile( FILE* fp ) const {
  if( useMicrosoftBOM ) {
    const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
    const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
    const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
    fputc( TIXML_UTF_LEAD_0, fp );
    fputc( TIXML_UTF_LEAD_1, fp );
    fputc( TIXML_UTF_LEAD_2, fp );
  }
  Print( fp, 0 );
  return ( ferror( fp ) == 0 );
}


void TiXmlDocument::CopyTo( TiXmlDocument* target ) const {
  TiXmlNode::CopyTo( target );
  target->error = error;
  target->errorId = errorId;
  target->errorDesc = errorDesc;
  target->tabsize = tabsize;
  target->errorLocation = errorLocation;
  target->useMicrosoftBOM = useMicrosoftBOM;
  TiXmlNode* node = 0;
  for( node = firstChild; node; node = node->NextSibling() ) {
    target->LinkEndChild( node->Clone() );
  }
}


TiXmlNode* TiXmlDocument::Clone() const {
  TiXmlDocument* clone = new TiXmlDocument();
  if( !clone ) {
    return 0;
  }
  CopyTo( clone );
  return clone;
}


void TiXmlDocument::Print( FILE* cfile, int depth ) const {
  assert( cfile );
  for( const TiXmlNode* node = FirstChild(); node; node = node->NextSibling() ) {
    node->Print( cfile, depth );
    fprintf( cfile, "\n" );
  }
}


bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const {
  if( visitor->VisitEnter( *this ) ) {
    for( const TiXmlNode* node = FirstChild(); node; node = node->NextSibling() ) {
      if( !node->Accept( visitor ) ) {
        break;
      }
    }
  }
  return visitor->VisitExit( *this );
}


const TiXmlAttribute* TiXmlAttribute::Next() const {
  if( next->value.empty() && next->name.empty() ) {
    return 0;
  }
  return next;
}



const TiXmlAttribute* TiXmlAttribute::Previous() const {
  if( prev->value.empty() && prev->name.empty() ) {
    return 0;
  }
  return prev;
}



void TiXmlAttribute::Print( FILE* cfile, int, TIXML_STRING* str ) const {
  TIXML_STRING n, v;
  EncodeString( name, &n );
  EncodeString( value, &v );
  if( value.find( '\"' ) == TIXML_STRING::npos ) {
    if( cfile ) {
      fprintf( cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
    }
    if( str ) {
      ( *str ) += n;
      ( *str ) += "=\"";
      ( *str ) += v;
      ( *str ) += "\"";
    }
  } else {
    if( cfile ) {
      fprintf( cfile, "%s='%s'", n.c_str(), v.c_str() );
    }
    if( str ) {
      ( *str ) += n;
      ( *str ) += "='";
      ( *str ) += v;
      ( *str ) += "'";
    }
  }
}


int TiXmlAttribute::QueryIntValue( int* ival ) const {
  if( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 ) {
    return TIXML_SUCCESS;
  }
  return TIXML_WRONG_TYPE;
}

int TiXmlAttribute::QueryDoubleValue( double* dval ) const {
  if( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 ) {
    return TIXML_SUCCESS;
  }
  return TIXML_WRONG_TYPE;
}

void TiXmlAttribute::SetIntValue( int _value ) {
  char buf [64];
  #if defined(TIXML_SNPRINTF)
  TIXML_SNPRINTF( buf, sizeof( buf ), "%d", _value );
  #else
  sprintf( buf, "%d", _value );
  #endif
  SetValue( buf );
}

void TiXmlAttribute::SetDoubleValue( double _value ) {
  char buf [256];
  #if defined(TIXML_SNPRINTF)
  TIXML_SNPRINTF( buf, sizeof( buf ), "%g", _value );
  #else
  sprintf( buf, "%g", _value );
  #endif
  SetValue( buf );
}

int TiXmlAttribute::IntValue() const {
  return atoi( value.c_str() );
}

double  TiXmlAttribute::DoubleValue() const {
  return atof( value.c_str() );
}


TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) {
  copy.CopyTo( this );
}


void TiXmlComment::operator=( const TiXmlComment& base ) {
  Clear();
  base.CopyTo( this );
}


void TiXmlComment::Print( FILE* cfile, int depth ) const {
  assert( cfile );
  for( int i = 0; i < depth; i++ ) {
    fprintf( cfile,  "    " );
  }
  fprintf( cfile, "<!--%s-->", value.c_str() );
}


void TiXmlComment::CopyTo( TiXmlComment* target ) const {
  TiXmlNode::CopyTo( target );
}


bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const {
  return visitor->Visit( *this );
}


TiXmlNode* TiXmlComment::Clone() const {
  TiXmlComment* clone = new TiXmlComment();
  if( !clone ) {
    return 0;
  }
  CopyTo( clone );
  return clone;
}


void TiXmlText::Print( FILE* cfile, int depth ) const {
  assert( cfile );
  if( cdata ) {
    int i;
    fprintf( cfile, "\n" );
    for( i = 0; i < depth; i++ ) {
      fprintf( cfile, "    " );
    }
    fprintf( cfile, "<![CDATA[%s]]>\n", value.c_str() );
  } else {
    TIXML_STRING buffer;
    EncodeString( value, &buffer );
    fprintf( cfile, "%s", buffer.c_str() );
  }
}


void TiXmlText::CopyTo( TiXmlText* target ) const {
  TiXmlNode::CopyTo( target );
  target->cdata = cdata;
}


bool TiXmlText::Accept( TiXmlVisitor* visitor ) const {
  return visitor->Visit( *this );
}


TiXmlNode* TiXmlText::Clone() const {
  TiXmlText* clone = 0;
  clone = new TiXmlText( "" );
  if( !clone ) {
    return 0;
  }
  CopyTo( clone );
  return clone;
}


TiXmlDeclaration::TiXmlDeclaration( const char * _version,
                                    const char * _encoding,
                                    const char * _standalone )
  : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) {
  version = _version;
  encoding = _encoding;
  standalone = _standalone;
}


#ifdef TIXML_USE_STL
TiXmlDeclaration::TiXmlDeclaration( const std::string& _version,
                                    const std::string& _encoding,
                                    const std::string& _standalone )
  : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) {
  version = _version;
  encoding = _encoding;
  standalone = _standalone;
}
#endif


TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
  : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) {
  copy.CopyTo( this );
}


void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) {
  Clear();
  copy.CopyTo( this );
}


void TiXmlDeclaration::Print( FILE* cfile, int, TIXML_STRING* str ) const {
  if( cfile ) {
    fprintf( cfile, "<?xml " );
  }
  if( str ) {
    ( *str ) += "<?xml ";
  }
  if( !version.empty() ) {
    if( cfile ) {
      fprintf( cfile, "version=\"%s\" ", version.c_str() );
    }
    if( str ) {
      ( *str ) += "version=\"";
      ( *str ) += version;
      ( *str ) += "\" ";
    }
  }
  if( !encoding.empty() ) {
    if( cfile ) {
      fprintf( cfile, "encoding=\"%s\" ", encoding.c_str() );
    }
    if( str ) {
      ( *str ) += "encoding=\"";
      ( *str ) += encoding;
      ( *str ) += "\" ";
    }
  }
  if( !standalone.empty() ) {
    if( cfile ) {
      fprintf( cfile, "standalone=\"%s\" ", standalone.c_str() );
    }
    if( str ) {
      ( *str ) += "standalone=\"";
      ( *str ) += standalone;
      ( *str ) += "\" ";
    }
  }
  if( cfile ) {
    fprintf( cfile, "?>" );
  }
  if( str ) {
    ( *str ) += "?>";
  }
}


void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const {
  TiXmlNode::CopyTo( target );
  target->version = version;
  target->encoding = encoding;
  target->standalone = standalone;
}


bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const {
  return visitor->Visit( *this );
}


TiXmlNode* TiXmlDeclaration::Clone() const {
  TiXmlDeclaration* clone = new TiXmlDeclaration();
  if( !clone ) {
    return 0;
  }
  CopyTo( clone );
  return clone;
}


void TiXmlUnknown::Print( FILE* cfile, int depth ) const {
  for( int i = 0; i < depth; i++ ) {
    fprintf( cfile, "    " );
  }
  fprintf( cfile, "<%s>", value.c_str() );
}


void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const {
  TiXmlNode::CopyTo( target );
}


bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const {
  return visitor->Visit( *this );
}


TiXmlNode* TiXmlUnknown::Clone() const {
  TiXmlUnknown* clone = new TiXmlUnknown();
  if( !clone ) {
    return 0;
  }
  CopyTo( clone );
  return clone;
}


TiXmlAttributeSet::TiXmlAttributeSet() {
  sentinel.next = &sentinel;
  sentinel.prev = &sentinel;
}


TiXmlAttributeSet::~TiXmlAttributeSet() {
  assert( sentinel.next == &sentinel );
  assert( sentinel.prev == &sentinel );
}


void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) {
  #ifdef TIXML_USE_STL
  assert( !Find( TIXML_STRING( addMe->Name() ) ) );
  #else
  assert( !Find( addMe->Name() ) );
  #endif
  addMe->next = &sentinel;
  addMe->prev = sentinel.prev;
  sentinel.prev->next = addMe;
  sentinel.prev      = addMe;
}

void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) {
  TiXmlAttribute* node;
  for( node = sentinel.next; node != &sentinel; node = node->next ) {
    if( node == removeMe ) {
      node->prev->next = node->next;
      node->next->prev = node->prev;
      node->next = 0;
      node->prev = 0;
      return;
    }
  }
  assert( 0 );
}


#ifdef TIXML_USE_STL
TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const {
  for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) {
    if( node->name == name ) {
      return node;
    }
  }
  return 0;
}

TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const std::string& _name ) {
  TiXmlAttribute* attrib = Find( _name );
  if( !attrib ) {
    attrib = new TiXmlAttribute();
    Add( attrib );
    attrib->SetName( _name );
  }
  return attrib;
}
#endif


TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const {
  for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) {
    if( strcmp( node->name.c_str(), name ) == 0 ) {
      return node;
    }
  }
  return 0;
}


TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const char* _name ) {
  TiXmlAttribute* attrib = Find( _name );
  if( !attrib ) {
    attrib = new TiXmlAttribute();
    Add( attrib );
    attrib->SetName( _name );
  }
  return attrib;
}


#ifdef TIXML_USE_STL
std::istream& operator>> ( std::istream & in, TiXmlNode & base ) {
  TIXML_STRING tag;
  tag.reserve( 8 * 1000 );
  base.StreamIn( &in, &tag );
  base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING );
  return in;
}
#endif


#ifdef TIXML_USE_STL
std::ostream& operator<< ( std::ostream & out, const TiXmlNode & base ) {
  TiXmlPrinter printer;
  printer.SetStreamPrinting();
  base.Accept( &printer );
  out << printer.Str();
  return out;
}


std::string& operator<< ( std::string& out, const TiXmlNode& base ) {
  TiXmlPrinter printer;
  printer.SetStreamPrinting();
  base.Accept( &printer );
  out.append( printer.Str() );
  return out;
}
#endif


TiXmlHandle TiXmlHandle::FirstChild() const {
  if( node ) {
    TiXmlNode* child = node->FirstChild();
    if( child ) {
      return TiXmlHandle( child );
    }
  }
  return TiXmlHandle( 0 );
}


TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const {
  if( node ) {
    TiXmlNode* child = node->FirstChild( value );
    if( child ) {
      return TiXmlHandle( child );
    }
  }
  return TiXmlHandle( 0 );
}


TiXmlHandle TiXmlHandle::FirstChildElement() const {
  if( node ) {
    TiXmlElement* child = node->FirstChildElement();
    if( child ) {
      return TiXmlHandle( child );
    }
  }
  return TiXmlHandle( 0 );
}


TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const {
  if( node ) {
    TiXmlElement* child = node->FirstChildElement( value );
    if( child ) {
      return TiXmlHandle( child );
    }
  }
  return TiXmlHandle( 0 );
}


TiXmlHandle TiXmlHandle::Child( int count ) const {
  if( node ) {
    int i;
    TiXmlNode* child = node->FirstChild();
    for( i = 0;
         child && i < count;
         child = child->NextSibling(), ++i ) {
    }
    if( child ) {
      return TiXmlHandle( child );
    }
  }
  return TiXmlHandle( 0 );
}


TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const {
  if( node ) {
    int i;
    TiXmlNode* child = node->FirstChild( value );
    for( i = 0;
         child && i < count;
         child = child->NextSibling( value ), ++i ) {
    }
    if( child ) {
      return TiXmlHandle( child );
    }
  }
  return TiXmlHandle( 0 );
}


TiXmlHandle TiXmlHandle::ChildElement( int count ) const {
  if( node ) {
    int i;
    TiXmlElement* child = node->FirstChildElement();
    for( i = 0;
         child && i < count;
         child = child->NextSiblingElement(), ++i ) {
    }
    if( child ) {
      return TiXmlHandle( child );
    }
  }
  return TiXmlHandle( 0 );
}


TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const {
  if( node ) {
    int i;
    TiXmlElement* child = node->FirstChildElement( value );
    for( i = 0;
         child && i < count;
         child = child->NextSiblingElement( value ), ++i ) {
    }
    if( child ) {
      return TiXmlHandle( child );
    }
  }
  return TiXmlHandle( 0 );
}


bool TiXmlPrinter::VisitEnter( const TiXmlDocument& ) {
  return true;
}

bool TiXmlPrinter::VisitExit( const TiXmlDocument& ) {
  return true;
}

bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) {
  DoIndent();
  buffer += "<";
  buffer += element.Value();
  for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() ) {
    buffer += " ";
    attrib->Print( 0, 0, &buffer );
  }
  if( !element.FirstChild() ) {
    buffer += " />";
    DoLineBreak();
  } else {
    buffer += ">";
    if( element.FirstChild()->ToText()
        && element.LastChild() == element.FirstChild()
        && element.FirstChild()->ToText()->CDATA() == false ) {
      simpleTextPrint = true;
    } else
    { DoLineBreak(); }
  }
  ++depth;
  return true;
}


bool TiXmlPrinter::VisitExit( const TiXmlElement& element ) {
  --depth;
  if( !element.FirstChild() ) {
  } else {
    if( simpleTextPrint ) {
      simpleTextPrint = false;
    } else
    { DoIndent(); }
    buffer += "</";
    buffer += element.Value();
    buffer += ">";
    DoLineBreak();
  }
  return true;
}


bool TiXmlPrinter::Visit( const TiXmlText& text ) {
  if( text.CDATA() ) {
    DoIndent();
    buffer += "<![CDATA[";
    buffer += text.Value();
    buffer += "]]>";
    DoLineBreak();
  } else if( simpleTextPrint ) {
    TIXML_STRING str;
    TiXmlBase::EncodeString( text.ValueTStr(), &str );
    buffer += str;
  } else {
    DoIndent();
    TIXML_STRING str;
    TiXmlBase::EncodeString( text.ValueTStr(), &str );
    buffer += str;
    DoLineBreak();
  }
  return true;
}


bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration ) {
  DoIndent();
  declaration.Print( 0, 0, &buffer );
  DoLineBreak();
  return true;
}


bool TiXmlPrinter::Visit( const TiXmlComment& comment ) {
  DoIndent();
  buffer += "<!--";
  buffer += comment.Value();
  buffer += "-->";
  DoLineBreak();
  return true;
}


bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown ) {
  DoIndent();
  buffer += "<";
  buffer += unknown.Value();
  buffer += ">";
  DoLineBreak();
  return true;
}

